{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Matrices and Matrix Operations\n",
    "\n",
    "This function introduces various ways to create\n",
    "matrices and how to use them in TensorFlow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.python.framework import ops\n",
    "ops.reset_default_graph()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Start a graph session"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "sess = tf.Session()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Declaring matrices\n",
    "\n",
    "Identity Matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  0.  0.]\n",
      " [ 0.  1.  0.]\n",
      " [ 0.  0.  1.]]\n"
     ]
    }
   ],
   "source": [
    "identity_matrix = tf.diag([1.0,1.0,1.0])\n",
    "print(sess.run(identity_matrix))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2x3 random norm matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-0.09611617  1.50501597  0.42943364]\n",
      " [ 0.04031758 -0.66115439 -0.91324311]]\n"
     ]
    }
   ],
   "source": [
    "A = tf.truncated_normal([2,3])\n",
    "print(sess.run(A))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2x3 constant matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 5.  5.  5.]\n",
      " [ 5.  5.  5.]]\n"
     ]
    }
   ],
   "source": [
    "B = tf.fill([2,3], 5.0)\n",
    "print(sess.run(B))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "3x2 random uniform matrix:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.34232175  0.16590214]\n",
      " [ 0.70915234  0.25312507]\n",
      " [ 0.11254978  0.03158247]]\n"
     ]
    }
   ],
   "source": [
    "C = tf.random_uniform([3,2])\n",
    "print(sess.run(C))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create matrix from np array:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  2.  3.]\n",
      " [-3. -7. -1.]\n",
      " [ 0.  5. -2.]]\n"
     ]
    }
   ],
   "source": [
    "D = tf.convert_to_tensor(np.array([[1., 2., 3.], [-3., -7., -1.], [0., 5., -2.]]))\n",
    "print(sess.run(D))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Matrix Operations\n",
    "\n",
    "Matrix addition/subtraction:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 3.69020724  5.68584728  4.3044405 ]\n",
      " [ 6.57195997  3.92733717  5.5748148 ]]\n",
      "[[ 0.  0.  0.]\n",
      " [ 0.  0.  0.]]\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(A+B))\n",
    "print(sess.run(B-B))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matrix Multiplication:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 5.  5.  5.]\n",
      " [ 5.  5.  5.]]\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(tf.matmul(B, identity_matrix)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matrix Transpose:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.11936677  0.07210469  0.06045544]\n",
      " [ 0.93742907  0.29088366  0.43557048]]\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(tf.transpose(C)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matrix Determinant:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-38.0\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(tf.matrix_determinant(D)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Matrix Inverse:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-0.5        -0.5        -0.5       ]\n",
      " [ 0.15789474  0.05263158  0.21052632]\n",
      " [ 0.39473684  0.13157895  0.02631579]]\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(tf.matrix_inverse(D)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cholesky Decomposition:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1.  0.  0.]\n",
      " [ 0.  1.  0.]\n",
      " [ 0.  0.  1.]]\n"
     ]
    }
   ],
   "source": [
    "print(sess.run(tf.cholesky(identity_matrix)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eigenvalues and Eigenvectors:  We use `tf.self_adjoint_eig()` function, which returns two objects, first one is an array of eigenvalues, the second is a matrix of the eigenvectors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-10.65907521  -0.22750691   2.88658212]\n",
      "[[ 0.21749542  0.63250104 -0.74339638]\n",
      " [ 0.84526515  0.2587998   0.46749277]\n",
      " [-0.4880805   0.73004459  0.47834331]]\n"
     ]
    }
   ],
   "source": [
    "eigenvalues, eigenvectors = sess.run(tf.self_adjoint_eig(D))\n",
    "print(eigenvalues)\n",
    "print(eigenvectors)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
